package yxy.cherry.paycenter.servlet.channel.weixin;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.dom4j.DocumentException;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import yxy.apple.logger.Logger;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.charge;
import yxy.cherry.paycenter.channelmodule.ActType;
import yxy.cherry.paycenter.channelmodule.sdk_jh.PayMoudle_jh;
import yxy.cherry.paycenter.channelmodule.weixin.PayMoudle_weixin;
import yxy.cherry.paycenter.database.dao.ordersDao;
import yxy.cherry.paycenter.database.db.orders;
import yxy.cherry.paycenter.servlet.channel.Servlet;
import yxy.cherry.paycenter.util.HttpUtil;
import yxy.cherry.paycenter.util.wxUtil;
import yxy.game.pm2.bean.Currency;
import yxy.game.pm2.bean.channel.SdkChannel;
import yxy.game.pm2.bean.module.OrderInfoModule;

/**
 * 微信 - ios - 支付回调
 * @author Dell
 *
 */
public class Servlet_WeiXinIos extends Servlet {

	private static final Logger logger = Logger.create(Servlet_WeiXinIos.class);
	
	private static final String success = "SUCCESS";	//交易结果 成功
	private static final String fail = "FAIL";	//交易结果 失败SUCCESS/FAIL
	
	@Override
	public String getUrl() {
		return "/sdk_" + getChannel() + PayMoudle_weixin.ios;
	}
	
	public Servlet_WeiXinIos() {
//		SdkService.getInstance().addServlet("/jh", new Servlet_jh());
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		super.doGet(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//		HttpUtil.printlnParseMap("post", req);
		String xml = HttpUtil.getPostData(req);
		logger.info("Servlet_WeiXinIos xml:" + xml);
		
		JSONObject infoobj = new JSONObject();
		try {
			infoobj = wxUtil.xml2Json(xml);
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		logger.info("Servlet_WeiXinIos: infoobj" + infoobj);
		
		JSONObject resultobj = new JSONObject();
		
		String return_code = infoobj.getString("return_code");
		String result_code = infoobj.getString("result_code");
		
		if(!return_code.equals("SUCCESS") || !result_code.equals("SUCCESS")) {
			resultobj.put("code", fail);
			resultobj.put("msg", "通知参数返回失败");
			returnInfo(resultobj, resp);
			return;
		}
		
//		appid	是	String(32)	wx8888888888888888	微信分配的小程序ID
//		mch_id	是	String(32)	1900000109	微信支付分配的商户号
//		device_info	否	String(32)	013467007045764	微信支付分配的终端设备号，
//		nonce_str	是	String(32)	5K8264ILTKCH16CQ2502SI8ZNMTM67VS	随机字符串，不长于32位
//		sign	是	String(32)	C380BEC2BFD727A4B6845133519F3AD6	签名，详见签名算法
//		sign_type	否	String(32)	HMAC-SHA256	签名类型，目前支持HMAC-SHA256和MD5，默认为MD5
//		result_code	是	String(16)	SUCCESS	SUCCESS/FAIL业务结果	
//		err_code	否	String(32)	SYSTEMERROR	错误返回的信息描述
//		err_code_des	否	String(128)	系统错误	错误返回的信息描述
//		openid	是	String(128)	wxd930ea5d5a258f4f	用户在商户appid下的唯一标识
//		is_subscribe	是	String(1)	Y	用户是否关注公众账号，Y-关注，N-未关注
//		trade_type	是	String(16)	JSAPI	JSAPI、NATIVE、APP
//		bank_type	是	String(32)	CMC	银行类型，采用字符串类型的银行标识，银行类型见银行列表
//		total_fee	是	Int	100	订单总金额，单位为分
//		settlement_total_fee	否	Int	100	应结订单金额=订单金额-非充值代金券金额，应结订单金额<=订单金额。
//		fee_type	否	String(8)	CNY	货币类型，符合ISO4217标准的三位字母代码，默认人民币：CNY，其他值列表详见货币类型
//		cash_fee	是	Int	100	现金支付金额订单现金支付金额，详见支付金额
//		cash_fee_type	否	String(16)	CNY	货币类型，符合ISO4217标准的三位字母代码，默认人民币：CNY，其他值列表详见货币类型
//		coupon_fee	否	Int	10	代金券金额<=订单金额，订单金额-代金券金额=现金支付金额，详见支付金额
//		coupon_count	否	Int	1	代金券使用数量
//		coupon_type_$n	否	String	CASH CASH--充值代金券 NO_CASH---非充值代金券 并且订单使用了免充值券后有返回（取值：CASH、NO_CASH）。$n为下标,从0开始编号，举例：coupon_type_0
//			注意：只有下单时订单使用了优惠，回调通知才会返回券信息。
//			下列情况可能导致订单不可以享受优惠：可能情况。
//		ID	coupon_id_$n	否	String(20)	10000	代金券ID,$n为下标，从0开始编号
//			注意：只有下单时订单使用了优惠，回调通知才会返回券信息。
//			下列情况可能导致订单不可以享受优惠：可能情况。
//		coupon_fee_$n	否	Int	100	单个代金券支付金额,$n为下标，从0开始编号
//		transaction_id	是	String(32)	1217752501201407033233368018	微信支付订单号
//		out_trade_no	是	String(32)	1212321211201407033568112322	商户系统内部订单号，要求32个字符内，只能是数字、大小写字母_-|*@ ，且在同一个商户号下唯一。
//		attach	否	String(128)	123456	商家数据包，原样返回
//		time_end	是	String(14)	20141030133525	支付完成时间，格式为yyyyMMddHHmmss，如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
		
		String transaction_id = infoobj.getString("transaction_id");
		String out_trade_no = infoobj.getString("out_trade_no");
		String attach = infoobj.getString("attach");
		
		orders o = ordersDao.getOrderByMyorderid(out_trade_no);
		if(o == null) {
			returnInfo(getReturnXml(fail, "订单不存在"), resp);
			return;
		}
		
		if(o.getOrderstate() == OrderInfoModule.orderinfofinish) {
			returnInfo(getReturnXml(success, "OK"), resp);
			return;
		}
		
		String sign = infoobj.getString("sign");
		
		JSONObject signjson = JSON.parseObject(infoobj.toString());
		signjson.remove("sign");
		
		String newsignstr = HttpUtil.getSignData(signjson, null, null);
		String newsignstr2 = newsignstr + "&key=" + "TNMiIN0hG2Zkn4QctxIJ9gEEZRL6s76o";
		
		String newsign = wxUtil.getMD5(newsignstr2).toUpperCase();
		if(!newsign.equals(sign)) {
			System.out.println("newsignstr2:" + newsignstr2);
			System.out.println("oldsign:" + sign);
			System.out.println("newsign:" + newsign);
			
			returnInfo(getReturnXml(fail, "验签失败"), resp);
			return;
		}
		
		o.setUpdatetime(new Date());
		o.setSubchannel(o.getChannel());
		o.setOrderstate(OrderInfoModule.orderinfofinish);
		o.setPayamount(Integer.valueOf(o.getGoodsprice()));
		o.setPlatorderid(transaction_id);
		ordersDao.update(o);
		
		ActType at = ActType.getat(o.getActtype());
		PayMoudle_jh am = new PayMoudle_jh();
		ArrayList<Currency> curs = am.getRewardInfoByType(o.getPlayercode(), at, o.getGoodsid());
		charge charge = DataCenter.getData(o.getGoodsid(), charge.class);
		am.createOrderInfoModule(o, curs, charge.getVipexp(), o.getGoodsprice());
		
		returnInfo(getReturnXml(success, "成功"), resp);
		logger.info("getReturnXml(success, \"成功\")" + getReturnXml(success, "OK"));
	}

	/**
	 * 返回信息到渠道
	 * 
	 * @param data
	 * @param resp
	 */
	public void returnInfo(String data, HttpServletResponse resp) {
		PrintWriter pw = null;
		resp.addHeader("Access-Control-Allow-Origin", "*");

		try {
			pw = resp.getWriter();
			pw.write(data);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (pw != null)
				pw.close();
		}
	}

	@Override
	public String getChannel() {
		return SdkChannel.sdk_weixin;
	}
	
	private String getReturnXml(String code, String msg) {
		HashMap<String, String> map = new HashMap<String, String>();
		map.put("code", code);
		map.put("msg", msg);
		
		return wxUtil.mapToXml(map, false);
	}
	
//	public static void main(String[] args) {
//
//		String xml = "<xml>\r\n"
//				+ "<appid><![CDATA[wxad14abacc407b9fd]]></appid>\r\n"
//				+ "<bank_type><![CDATA[CMB_CREDIT]]></bank_type>\r\n"
//				+ "<cash_fee><![CDATA[1]]></cash_fee>\r\n"
//				+ "<fee_type><![CDATA[CNY]]></fee_type>\r\n"
//				+ "<is_subscribe><![CDATA[N]]></is_subscribe>\r\n"
//				+ "<mch_id><![CDATA[1602430099]]></mch_id>\r\n"
//				+ "<nonce_str><![CDATA[QvkhCctdMYggLQ1s]]></nonce_str>\r\n"
//				+ "<openid><![CDATA[oMbHu4pBE9STW2WjF2MXQxl6NY6M]]></openid>\r\n"
//				+ "<out_trade_no><![CDATA[IOS20210528545114138921]]></out_trade_no>\r\n"
//				+ "<result_code><![CDATA[SUCCESS]]></result_code>\r\n"
//				+ "<return_code><![CDATA[SUCCESS]]></return_code>\r\n"
//				+ "<sign><![CDATA[E567F93D25AAD8037348C8501B1A14A5]]></sign>\r\n"
//				+ "<time_end><![CDATA[20210528114150]]></time_end>\r\n"
//				+ "<total_fee>1</total_fee>\r\n"
//				+ "<trade_type><![CDATA[JSAPI]]></trade_type>\r\n"
//				+ "<transaction_id><![CDATA[4200001023202105280545901620]]></transaction_id>\r\n"
//				+ "</xml>";
//		
//		logger.info("Servlet_WeiXinIos xml:" + xml);
//		
//		JSONObject infoobj = new JSONObject();
//		try {
//			infoobj = wxUtil.xml2Json(xml);
//		} catch (DocumentException e) {
//			e.printStackTrace();
//		}
//		logger.info("Servlet_WeiXinIos: infoobj:" + infoobj);
//		
//		JSONObject resultobj = new JSONObject();
//		
//		String return_code = infoobj.getString("return_code");
//		String result_code = infoobj.getString("result_code");
//		
//		if(!return_code.equals("SUCCESS") || !result_code.equals("SUCCESS")) {
//			resultobj.put("code", fail);
//			resultobj.put("msg", "通知参数返回失败");
////			returnInfo(resultobj, resp);
////			return;
//		}
//		
////		appid	是	String(32)	wx8888888888888888	微信分配的小程序ID
////		mch_id	是	String(32)	1900000109	微信支付分配的商户号
////		device_info	否	String(32)	013467007045764	微信支付分配的终端设备号，
////		nonce_str	是	String(32)	5K8264ILTKCH16CQ2502SI8ZNMTM67VS	随机字符串，不长于32位
////		sign	是	String(32)	C380BEC2BFD727A4B6845133519F3AD6	签名，详见签名算法
////		sign_type	否	String(32)	HMAC-SHA256	签名类型，目前支持HMAC-SHA256和MD5，默认为MD5
////		result_code	是	String(16)	SUCCESS	SUCCESS/FAIL业务结果	
////		err_code	否	String(32)	SYSTEMERROR	错误返回的信息描述
////		err_code_des	否	String(128)	系统错误	错误返回的信息描述
////		openid	是	String(128)	wxd930ea5d5a258f4f	用户在商户appid下的唯一标识
////		is_subscribe	是	String(1)	Y	用户是否关注公众账号，Y-关注，N-未关注
////		trade_type	是	String(16)	JSAPI	JSAPI、NATIVE、APP
////		bank_type	是	String(32)	CMC	银行类型，采用字符串类型的银行标识，银行类型见银行列表
////		total_fee	是	Int	100	订单总金额，单位为分
////		settlement_total_fee	否	Int	100	应结订单金额=订单金额-非充值代金券金额，应结订单金额<=订单金额。
////		fee_type	否	String(8)	CNY	货币类型，符合ISO4217标准的三位字母代码，默认人民币：CNY，其他值列表详见货币类型
////		cash_fee	是	Int	100	现金支付金额订单现金支付金额，详见支付金额
////		cash_fee_type	否	String(16)	CNY	货币类型，符合ISO4217标准的三位字母代码，默认人民币：CNY，其他值列表详见货币类型
////		coupon_fee	否	Int	10	代金券金额<=订单金额，订单金额-代金券金额=现金支付金额，详见支付金额
////		coupon_count	否	Int	1	代金券使用数量
////		coupon_type_$n	否	String	CASH CASH--充值代金券 NO_CASH---非充值代金券 并且订单使用了免充值券后有返回（取值：CASH、NO_CASH）。$n为下标,从0开始编号，举例：coupon_type_0
////			注意：只有下单时订单使用了优惠，回调通知才会返回券信息。
////			下列情况可能导致订单不可以享受优惠：可能情况。
////		ID	coupon_id_$n	否	String(20)	10000	代金券ID,$n为下标，从0开始编号
////			注意：只有下单时订单使用了优惠，回调通知才会返回券信息。
////			下列情况可能导致订单不可以享受优惠：可能情况。
////		coupon_fee_$n	否	Int	100	单个代金券支付金额,$n为下标，从0开始编号
////		transaction_id	是	String(32)	1217752501201407033233368018	微信支付订单号
////		out_trade_no	是	String(32)	1212321211201407033568112322	商户系统内部订单号，要求32个字符内，只能是数字、大小写字母_-|*@ ，且在同一个商户号下唯一。
////		attach	否	String(128)	123456	商家数据包，原样返回
////		time_end	是	String(14)	20141030133525	支付完成时间，格式为yyyyMMddHHmmss，如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
//		
//		String sign = infoobj.getString("sign");
//		
//		JSONObject signjson = JSON.parseObject(infoobj.toString());
//		signjson.remove("sign");
//		
//		String newsignstr = HttpUtil.getSignData(signjson, null, null);
//		String newsignstr2 = newsignstr + "&key=" + "TNMiIN0hG2Zkn4QctxIJ9gEEZRL6s76o";
//		
//		String newsign = wxUtil.getMD5(newsignstr2).toUpperCase();
//		if(!newsign.equals(sign)) {
//			System.out.println("newsignstr2:" + newsignstr2);
//			System.out.println("oldsign:" + sign);
//			System.out.println("newsign:" + newsign);
//			
////			returnInfo(getReturnXml(fail, "验签失败"), resp);
////			return;
//		}
//		
//		String transaction_id = infoobj.getString("transaction_id");
//		String out_trade_no = infoobj.getString("out_trade_no");
//		String attach = infoobj.getString("attach");
//		
////		orders o = ordersDao.getOrderByMyorderid(out_trade_no);
////		if(o == null) {
//////			returnInfo(getReturnXml(fail, "订单不存在"), resp);
////			return;
////		}
//		
////		o.setPlatorderid(transaction_id);
////		o.setOrderstate(OrderInfoModule.orderinfofinish);
////		ordersDao.update(o);
//		
////		ActType at = ActType.getat(o.getActtype());
////		PayMoudle_jh am = new PayMoudle_jh();
////		ArrayList<Currency> curs = am.getRewardInfoByType(o.getPlayercode(), at, o.getGoodsid());
////		charge charge = DataCenter.getData(o.getGoodsid(), charge.class);
////		am.createOrderInfoModule(o, curs, charge.getVipexp(), o.getGoodsprice());
//		
////		returnInfo(getReturnXml(success, "成功"), resp);
////		System.out.println("getReturnXml(success, \"订单不存在\"):" + getReturnXml(success, "订单不存在"));
//	
//	}
}
